import { reactive, ref } from 'vue';
import { useUserStore } from '@/stores/user'
import { stopchatApi } from '@/api/app';
import { ElMessage } from 'element-plus';
import { getApiUrl} from '@/utils/config';
// 获取六位随机字符串
const socketToToken = ref(''); // 单词socket的链接唯一标识
const socketLink = ref(false); // 链接成功与否
export function getRandomString(length: number = 6): string {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; // 字符池
  const charsLength = chars.length;
  let result = '';
  while (result === '' || result === socketToToken.value) {
    result = '';
    for (let i = 0; i < length; i++) {
      // 随机选取字符池中的一个字符
      result += chars.charAt(Math.floor(Math.random() * charsLength));
    }
  }
  return result;
}
const socket = ref<any>(null); // Socket.IO 实例

export const socketConnect = (serveMsg:Function, link:Function) => {
  if (typeof window.io !== 'undefined') {
    try {
      socket.value = (window as any).io(getApiUrl(),{ autoConnect: false }); // 使用全局 io 对象
      // 监听连接状态
      socket.value.on('connect', () => {
        socketLink.value = true;
        socketToToken.value = getRandomString();
        socket.value.emit("login", socketToToken.value); // 发送登录信息
        link(socketToToken.value); // 组件中用来判断当前是否重连成功
        console.log('Socket.IO 连接',new Date().getTime(), socketToToken.value)
      });
      socket.value.on('disconnect', () => {
        socketLink.value = false;
        console.log('Socket.IO 已断开连接');
      });
      // 接收到的消息
      socket.value.on("server_msg", (data: any) => {
        const res = isJSON(decodeHTML(data))
        if(res.code === 1 || res.code === 2 || res.code === 6){
          console.log('接收到code==1 || 2的消息----', res,new Date().getTime() )
          serveMsg(res);
        }else if(res.code === 0){
          console.log('接收到的消息----code == 0', res)
        }else{
          console.log('接收到的消息----', res,new Date().getTime())
          serveMsg({code:3, errmsg:'返回数据结构不正确', msg:res })
        }
      });
      // 错误处理
      socket.value.on('error', (err: any) => {
        serveMsg({code:0, errmsg:'Socket.IO 错误处理', ...err})
      });
    } catch (err) {
      serveMsg({code:0, errmsg:'Socket.IO 初始化失败', msg: err})
    }
  } else {
    serveMsg({code:0, errmsg:'Socket.IO 未正确加载', msg:''})
  }
};
// 发送消息
export const sendMsg = (data:any) => {
  const userStore = useUserStore()
  if( !socket.value ) return ElMessage.error('Socket.IO 初始化失败,请稍后再试');
  const sendData = { 
    token:userStore.token, 
    to:socketToToken.value, // 当前对话的标识
    msg: data.msg, // 发送具体内容
    topic: data.topic, // 历史对话id
    type: data.type, // 类型 1-对话， 2-助手， 3-应用
    sourceModel:data.sourceModel || 1, // 资源 1-星火，2-DeepseekR1，3-DeepseekV1
  }
  console.log('发送消息传参', sendData,new Date().getTime());
  socket.value.emit("send_message", JSON.stringify(sendData));
}
// 页面关闭 断开链接
export const disconnect = () => {
  socket.value && socket.value.disconnect(); // 断开连接
  socket.value = null; 
}


// 模拟打字机效果（使用 requestAnimationFrame）
const printData = reactive({
  socketEnd:false, // 流式数据结束是否结束
  data:'', // 需要打印的全部内容 => 当前的回答内容
  stop:false, // 当前打印是否打印
  animationId:0, // 保存 requestAnimationFrame 的 ID
})
// 打印数据  runFun-抛出当前打印的数据， endFun-抛出打印结束的状态
export const printText = (runFun:Function, endFun:Function) => {
  const printEndData = ref<string>(''); // 已打印的内容
  const printCurIndex = ref<number>(0); // 当前打印文本的位置
  printData.socketEnd = false;
  printData.stop = false;
  // console.log('--------------', printData.stop )
  const animateType = () => {
    if (printData.socketEnd && printCurIndex.value > 0 && printCurIndex.value == printData.data.length || printData.stop) {
      console.log('打印完成');
      endFun(2); // 打印结束
      cancelAnimationFrame(printData.animationId); // 停止动画帧
    }else{
      if (printCurIndex.value < printData.data.length && !printData.stop) {
        printEndData.value += printData.data[printCurIndex.value];
        printCurIndex.value++;
        if(printEndData.value){
          runFun(printEndData.value);
          endFun(1); // 打印中
        }
      }
      // console.log('请求下一帧动画---------------', printData.stop )
      // 请求下一帧动画
      printData.animationId = requestAnimationFrame(animateType);
    }
  };
  // 启动打字机动画
  printData.animationId = requestAnimationFrame(animateType);
};



// 结束打印数据
export const printAddEnd = () => {
  socket.value && socket.value.disconnect();
  printData.socketEnd = true;
}
// 向打印机中添加数据
export const printAddCon = (msg:string) => {
  printData.data= msg;
}
// socket 建连
export const connect = () =>{
  return new Promise((resolve, reject) => {
    stopchatApi({to: socketToToken.value}).then(() => {
      // 当socket时链接状态时先进行断联
      if(socket.value && socketLink.value){
        socket.value.disconnect();
        console.log('手动断联后')
      }
      // 暂停之前的打印逻辑
      if (printData.animationId) {
        cancelAnimationFrame(printData.animationId); // 取消当前的动画帧
        printData.stop = true; // 标记打印已停止
        console.log('打印已手动停止', printData.stop, printData.animationId);
      }
      printAddEnd();
      socket.value.connect(); // 重新链接socket
      console.log('尝试重新连接');
      resolve(2); // 2-结束本次对话
    }).catch((error:any) => {
      reject(error);
    });
  });
}
// 中断对话
export const stopchat = () => {
  return new Promise((resolve, reject) => {
    stopchatApi({to: socketToToken.value}).then(() => {
      socket.value && socket.value.disconnect();
      if (printData.animationId) {
        cancelAnimationFrame(printData.animationId); // 取消当前的动画帧
        printData.stop = true; // 标记打印已停止
        console.log('打印已手动停止', printData.stop, printData.animationId);
      }
      printAddEnd();
      resolve(2); // 2-结束本次对话
    }).catch((error:any) => {
      reject(error);
    });
  });
};

function decodeHTML(encodedString:any) {
  const entityMap = {
    '&lt;': '<',
    '&gt;': '>',
    '&amp;': '&',
    '&quot;': '"',
    '&#039;': "'",
    // 可以添加更多的HTML实体及其对应的字符
  };

  // 使用正则表达式匹配HTML实体，并进行替换
  return encodedString.replace(/&(#?)(\d{1,5}|\w{1,8});/g, function (match, isNumeric, entity) {
    return entityMap[match] || match;
  });
}
function isJSON(decodedString: string) {
  try {
    return JSON.parse(decodedString); // 尝试解析为 JSON
  } catch (e) {
    console.warn('无法解析为 JSON:', decodedString);
    return { msg: decodedString }; // 如果不是 JSON，返回默认结构
  }
}
